package cn.springcloud.fix.gateway.filter;

import cn.springcloud.fix.common.core.base.R;
import cn.springcloud.fix.common.core.utils.json.JsonUtil;
import cn.springcloud.fix.gateway.config.IgnoreUrlProperties;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.Arrays;

/**
 * Spring Cloud Gateway根据作用范围划分为GatewayFilter和GlobalFilter，二者区别如下：
 * https://blog.csdn.net/forezp/article/details/85057268
 */
@Slf4j
@Component
public class GlobalRequestFilter implements GlobalFilter, Ordered {

    // @Autowired
    // private RemoteAuthService remoteAuthService;

    private static final String[] whiteList = {"/auth/login", "/user/register"};

    @Autowired
    private IgnoreUrlProperties ignoreUrlProperties;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String url = request.getURI().getPath();
        log.info("url:{}", url);
        HttpHeaders httpHeaders = exchange.getRequest().getHeaders();
        return chain.filter(exchange);

        // String authentication = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
        // String header = exchange.getRequest().getHeaders().getFirst("header");
        // if (StringUtils.isBlank(header)) {
        //     return fallback(exchange, HttpStatus.UNAUTHORIZED, "header can't be null or empty");
        // }
        //
        // String method = request.getMethodValue();
        // String path = request.getPath().value();
        // String rawPath = request.getURI().getRawPath();
        // log.debug("path:{},rawPath:{},method:{},header:{}", path, rawPath, method, header);
        //
        // // 跳过不需要验证的路径
        // if (Arrays.asList(whiteList).contains(url)) {
        //     return chain.filter(exchange);
        // }
        //
        // if (ignoreAuthentication(path)) {
        //     return chain.filter(exchange);
        // }
        //
        // //检验权限
        // R<String> r = remoteAuthService.hasPermission(path, method, authentication);
        // if (r.getCode() != 0) {
        //     return fallback(exchange, HttpStatus.UNAUTHORIZED, r.getMsg());
        // }
        //
        // return fallback(exchange, HttpStatus.UNAUTHORIZED, "xxx");

        // ServerHttpRequest newRequest = request.mutate().path(rawPath).build();
        // ServerHttpRequest newRequest = request.mutate()
        //         .header("header", header)
        //         .header("access_token", "xxoo").build();
        // return chain.filter(exchange.mutate().request(newRequest).build());
    }

    private boolean ignoreAuthentication(String path) {
        return ignoreUrlProperties.getUrls().stream().anyMatch(o -> path.startsWith(StringUtils.trim(o)));
        // return Stream.of(this.ignoreUrls.split(",")).anyMatch(ignoreUrl -> url.startsWith(StringUtils.trim(ignoreUrl)));
    }

    private Mono<Void> fallback(ServerWebExchange exchange, HttpStatus httpStatus, String msg) {
        ServerHttpResponse originalResponse = exchange.getResponse();
        originalResponse.setStatusCode(httpStatus);
        originalResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        byte[] res = JSON.toJSONString(R.ERROR(httpStatus.value(), msg)).getBytes();
        DataBuffer buffer = originalResponse.bufferFactory().wrap(res);
        return originalResponse.writeWith(Flux.just(buffer));
    }

    @Override
    public int getOrder() {
        return -1000;
    }
}
